{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "92491da6",
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf  #引入TensorFlow包，并简称tf\n",
    "hello = tf.constant('Hello, TensorFlow!')  #定义一个常量\n",
    "print(hello)  #运行生成”Hello,TensorFlow！”"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "84c62210",
   "metadata": {},
   "source": [
    "## 静态图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e9710cb0",
   "metadata": {},
   "outputs": [],
   "source": [
    "#1.X版本在2.X中执行\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "977afe19",
   "metadata": {},
   "source": [
    "## 动态图"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b24a7bd",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "id": "6bdba909",
   "metadata": {},
   "source": [
    "## 8.3 Tensor的基本操作"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "62e1f335",
   "metadata": {},
   "source": [
    "### 1、 张量的类型\n",
    "TensorFlow 支持以下两种类型的张量：常量和变量。在1.X版本中还有占位符这种类型。\n",
    "\n",
    "*常量（tf.constant）：常量是其值不能改变的张量\n",
    "\n",
    "*变量（tf.Variable）：当一个量在会话中的值需要更新时，使用变量来表示。\n",
    "\n",
    "*占位符（tf.placeholder）：属于Variable变量类型。在定义时不需要赋值，但在使用之前必须赋值（feed）的变量，可以用数据通过feed_dict给填充进去就可以，通常用作训练数据。在TensorFlow 2.X不兼容该类型，该类型只是在TensorFlow 1.X的计算图中，它们可以和 feed_dict 一起使用来输入数据。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "008fe03d",
   "metadata": {},
   "outputs": [],
   "source": [
    "t1=tf.constant(1,dtype=tf.float32) #声明一个float32类型，值为1的常量。\n",
    "print(t1)\n",
    "t2=tf.constant([1,2,3,4],dtype=tf.float32) #声明一个float32类型，型如[1,2,3,4]的常量。\n",
    "print(t2)\n",
    "t3=tf.constant([[1,2],[3,4]],dtype=tf.float32) #声明一个float32类型的2维常量。\n",
    "print(t3)\n",
    "t4=tf.constant([[[1,2],[3,4]],[[5,6],[7,8]]],dtype=tf.float32) #声明一个float32类型的3维常量。\n",
    "print(t4)\n",
    "v=tf.Variable([1,2,3]) #创建变量v，为一个array\n",
    "print(v)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "1a6f89aa",
   "metadata": {},
   "source": [
    "### 2、创建张量"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "df74a49c",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_1=tf.zeros([2,3],tf.int32)  #结果是一个2*3的全0矩阵，形如:[[0 0 0],[0 0 0]]\n",
    "print(t_1)\n",
    "t_2= tf.ones([2,3],tf.int32)  #结果是一个2*3的全1矩阵，形如:[[1 1 1],[1 1 1]]\n",
    "print(t_2)\n",
    "\n",
    "t_3=tf.zeros_like(t_1)   #创建一个与t_1形状相同的全0矩阵\n",
    "print(t_3)\n",
    "\n",
    "t_4=tf.ones_like(t_2)   #创建一个与t_2形状相同的全1矩阵\n",
    "print(t_4)\n",
    "\n",
    "t_5= tf.linspace(2.0,5.0,5) #start到end，5表示个数等间隔的。start和end这两个数字必须是浮点#输出:[2. ,2.75, 3.5, 4.25, 5.] 相应的值为 (stop-start)/(num-1)\n",
    "print(t_5)\n",
    "\n",
    "t_6= tf.range(10)    #输出:[0 1 2 3 4 5 6 7 8 9]\n",
    "#print(t_6)\n",
    "\n",
    "t_7=tf.random.normal([2,3],mean=2.0,stddev=4,seed=12)#mean均值 ，stddev 标准差，seed随机种子\n",
    "#print(t_7)\n",
    "\n",
    "t_8=tf.random.truncated_normal([1,5],stddev=2,seed=12)#从截断的正态分布中输出随机值，生成的值服从具有指定平均值和标准偏差的正态分布\n",
    "#print(t_8)\n",
    "\n",
    "t_9=tf.random.uniform([2,3],maxval=4,seed=12)#从均匀分布中输出随机值生成的值，在该[minval, maxval)范围内遵循均匀分布\n",
    "print(t_9)\n",
    "\n",
    "t_10=tf.fill([2,3],5) \n",
    "print(t_10)\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "e25bdad0",
   "metadata": {},
   "source": [
    "### 3、张量的运算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3cff28f9",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_11= tf.constant([[1,2],[-3,4]])\n",
    "t_12= tf.constant([[5,6],[7,8]])\n",
    "t_13=t_11+t_12\n",
    "print(t_13)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "391134cd",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_14=tf.constant([[3,6],[9,12]])\n",
    "t_15=tf.divide(t_14,3)  #也可写成t_15=t_14/3\n",
    "print(t_15)  #输出：tf.Tensor([[1. 2.] [3. 4.]], shape=(2, 2), dtype=float64)\n",
    "t_16=tf.multiply(t_14,3)  #也可写成 t_16=t_14*3\n",
    "print(t_16) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "4e8ea2d3",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_17=tf.range(1,10,2)  \n",
    "t_18=t_17+1  #t_17中每个元素都加1  ,广播运算\n",
    "print(t_18) "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bde74c13",
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "t_19=tf.constant([[1,2,3],[4,5,6]])\n",
    "#如果axis=0 表示纵向操作，axis=1表示横向操作\n",
    "tf.reduce_mean(t_19,axis=0)# 求列平均\n",
    "print(tf.reduce_sum(t_19,axis=0))  #求列和\n",
    "print(tf.reduce_max(t_19,axis=1))  #求行最大值\n",
    "print(tf.argmax(t_19,axis=1))#求行最大值索引\n",
    "print(tf.size(t_19)) #计算元素个数\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a6a5b93b",
   "metadata": {},
   "outputs": [],
   "source": [
    "t_20=tf.constant(2)\n",
    "t_21=tf.constant(3)\n",
    "print(tf.equal(t_20,t_21))  #判断相等，输出：tf.Tensor(False, shape=(), dtype=bool)\n",
    "print(tf.not_equal(t_20,t_21)) \n",
    "print(tf.less(t_20,t_21)) #小于，输出：tf.Tensor(True, shape=(), dtype=bool)\n",
    "print(tf.greater(t_20,t_21))  \n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bf61a3e8",
   "metadata": {},
   "outputs": [],
   "source": [
    "#逻辑运算共有以下4种：\n",
    "#(1) 与：lgical_and\n",
    "#(2) 或：logical_or\n",
    "#(3) 非：logical_not\n",
    "#(4) 异或：logical_xor\n",
    "print(tf.logical_not(tf.greater_equal(t_20,t_21)))  #逻辑非\n",
    "print(tf.logical_or(tf.greater(t_20,t_21),tf.equal(t_20,t_21))) #逻辑或\n",
    "#TensorFlow的计算图是强类型语言，逻辑运算必须是布尔型值，如果是其他类型，将报错。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7736f9f6",
   "metadata": {},
   "outputs": [],
   "source": [
    "#矩阵运算\n",
    "t_22=tf.constant([[1,2],[3,4],[5,6]])\n",
    "t_23= tf.constant([[10,20,30],[1,1,1]])\n",
    "print(tf.transpose(t_22)) #矩阵转置\n",
    "print(tf.matmul(t_22,t_23)) #矩阵点积np.dot()，也可使用@进行运算\n",
    "t_24=tf.constant([[1.,2.],[3.,4.]])\n",
    "print(tf.linalg.det(t_24))  #行列式求值\n",
    "print(tf.linalg.inv(t_24))  #逆矩阵\n",
    "print(tf.linalg.trace(t_24))  #求迹                                \n",
    "print(tf.linalg.diag(t_24)) #生成对角矩阵\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1620171c",
   "metadata": {},
   "outputs": [],
   "source": [
    "#向量拼接\n",
    "t_25=[[1,2,3],[4,5,6]]\n",
    "t_26=tf.concat([t_25,t_23],0) #轴参数为0\n",
    "print(t_26) \n",
    "a_3=tf.concat([t_25,t_23],1) \n",
    "print(a_3)\n",
    "#维度变换\n",
    "t_27= tf.random.normal([4, 28, 28, 3]) #假设为4张28*28，3通道的图片\n",
    "print(t_27.shape)  #输出：TensorShape([4, 28, 28, 3]) #\n",
    "print(tf.reshape(t_27, [4, 784, 3]).shape)\n",
    "#增加维度\n",
    "t_28= tf.random.normal([4, 25, 8])\n",
    "print(t_28.shape)  #输出：TensorShape([4, 25, 8])\n",
    "print(tf.expand_dims(t_28, axis=1).shape)  #在第1维增加维度\n",
    "print(tf.expand_dims(t_28, axis=-1).shape)\n",
    "#挤压维度\n",
    "print(tf.squeeze(tf.zeros([1,2,1,1,3])).shape ) #删除某一维度是1的维度\n",
    "print(tf.squeeze(tf.zeros([1,2,1,1,3]),axis=0).shape ) #也可通过axis指定维度\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "802b24ba",
   "metadata": {},
   "source": [
    "### 4、索引和切片\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "982d53ca",
   "metadata": {},
   "outputs": [],
   "source": [
    "a=tf.random.normal([2,5,5,3]) #四维tensor\n",
    "print(a[0].shape)  #相当于是第0个班级的所有数据，它包含5名同学，每名有5门科目，每科目有3份作业。因此，a[0] 是一个三维tensor，形状为[5,5,3] \n",
    "print(a[0][0].shape)  #相当于第0个班级的第0个同学的所有数据，包含5门科目，每科目有3份作业。因此，是一个二维tensor，形状为[5,3] ，等同于a[0,0]\n",
    "print(a[0][0][0].shape)  #相当于是第0个班的第0个学生的第0门课程的所有作业，是一个向量，形状为[3]，等同于a[0,0,0]\n",
    "print(a[0][0][0][1].shape)  #值为标量1，是0维tensor，等同于a[0,0,0,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "5ee252df",
   "metadata": {},
   "outputs": [],
   "source": [
    "a1=tf.range(10) \n",
    "print(a1[3:6]) #获取3，4，5\n",
    "print(a1[:3]) #获取前3个数据，即[0, 1, 2]\n",
    "print(a1[-4:-1])  #获取倒数第4个到倒数第1个数据\n",
    "print(a1[:]) #返回所有元素\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "71445de8",
   "metadata": {},
   "outputs": [],
   "source": [
    "a=tf.random.normal([2,5,5,3]) #四维tensor\n",
    "print(a[0,:,:,:].shape) \n",
    "print(a[:,:,:,2].shape )\n",
    "print(a[:,2,:,:].shape )"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "bc1a485c",
   "metadata": {},
   "outputs": [],
   "source": [
    "a2=tf.ones([4,5,6,3]) #有4幅图像，每幅图像是5*6大小的3个通道\n",
    "a2[:,1:5:2,:4:2,:].shape\n",
    "a3=tf.range(5)  #创建0-4的tensor，即[0,1,2,3,4]\n",
    "a3[::-1]  #逆序排序，结果为：[4, 3, 2, 1, 0]\n",
    "a3[4::-2]  #逆序，结果为[4, 2, 0]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1f5f08b3",
   "metadata": {},
   "outputs": [],
   "source": [
    "#省略号方法\n",
    "a=tf.random.normal([2,5,5,3]) #四维tensor\n",
    "a[0]\n",
    "a[0,:,:,:]\n",
    "a[0,...]\n",
    "a[0,...,1]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "78b32214",
   "metadata": {},
   "outputs": [],
   "source": [
    "#tf.gather()函数是指定某一个维度，按照指定索引获取数据，语法形式为：\n",
    "#tf.gather(tensor, axis, indices=[ ])\n",
    "a4=tf.zeros([4,35,8]) #创建全0张量，假设a4是[班级、学生、科目]\n",
    "print(tf.gather(a4,axis=0,indices=[2,3]).shape) #指定维度为0，即班级，indices指定收集顺序，查看第2、3班级的所有数据\n",
    "print(tf.gather(a4,axis=1,indices=[4,30,17,9]).shape) #作用是指定维度为1，即学生，收集索引号为4、30、17、9这四个学生的数据\n",
    "a4_1=tf.gather(a4,axis=1,indices=[4,30,17,9]) #取出这4名学生的全部信息\n",
    "a4_2=tf.gather(a4_1,axis=2,indices=[6,1,4]) #axis=2指定科目，获取6,1,4科目信息，shape为[4,4,3]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "cc39e4db",
   "metadata": {},
   "outputs": [],
   "source": [
    "#语法形式为：tf.gather_nd(tensor, indices)\n",
    "#其作用是按照 indices 的格式从传入的tensor中抽取切片（合并为一个Tensor）indices是一个K维整数Tensor。\n",
    "a4=tf.zeros([4,35,8])\n",
    "a4_3=tf.gather_nd(a4,[0]).shape  #获取第[[0]]个班级所有数据，返回的shape减少一个维度，即[35, 8]\n",
    "print(a4_3)\n",
    "a4_4=tf.gather_nd(a4,[0,1]).shape  #获取0号班级第1个学生的数据，返回的shape少两个维度，即[8]\n",
    "print(a4_4)\n",
    "a4_5=tf.gather_nd(a4,[0,1,2]).shape   #获取第0个班级的第1个学生的第2门课的数据，是一个值，因此返回的shape为 []\n",
    "print(a4_5)\n",
    "a4_6=tf.gather_nd(a4,[[0,1,2],[1,5,7]])  #第0个班级的第1个学生的第2门课和第1个班级第5个学生的第7门课放在一个列表中。\n",
    "print(a4_6)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "1402e302",
   "metadata": {},
   "outputs": [],
   "source": [
    "#布尔索引选数据\n",
    "#tf.boolean_mask(tensor, mask=布尔标记, axis=指定维度)\n",
    "#其中，mask的shape要和指定维度的tensor的shape相同。输出mask标记为True的值\n",
    "a5=tf.ones([3,35,5,10])\n",
    "a5_1=tf.boolean_mask(a5,mask=[True,False,True]).shape\n",
    "print(a5_1)\n",
    "a5_2=tf.boolean_mask(a5,mask=[True,False,True,True,False],axis=2).shape\n",
    "print(a5_2)\n",
    "a6=tf.random.normal([2,3,4])\n",
    "print(a6)\n",
    "tf.boolean_mask(a6,mask=[[True,False,False],[False,True,True]]) #获取第0个班级，第0个学生的所有信息，和第1个班级第2、3个学生的所有信息\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "3b3e5f8f",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.8.12"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
